package site.wetsion.galio.sdk.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.util.Pool;
import site.wetsion.galio.sdk.common.GalioClientDetailsProperties;
import site.wetsion.galio.sdk.common.GalioOauthAccessToken;
import site.wetsion.galio.sdk.common.UserDetails;
import java.util.Objects;

/**
 * 获取资源的工具API
 *
 * @author weixin
 * @version 1.0
 * @CLassName ResourceUtil
 * @date 2019/3/18 7:12 PM
 */
public class ResourceUtil {

    private final static Logger logger = LoggerFactory.getLogger(ResourceUtil.class);

    private GalioClientDetailsProperties galioClientDetailsProperties;

    protected Pool<Jedis> jedisPool = null;

    public ResourceUtil(GalioClientDetailsProperties galioClientDetailsProperties) {
        this.galioClientDetailsProperties = galioClientDetailsProperties;
        this.initRedis();
    }

    private void initRedis() {

        GalioClientDetailsProperties.Redis redis =
                Objects.isNull(this.galioClientDetailsProperties.getRedis())
                        ? new GalioClientDetailsProperties.Redis() : this.galioClientDetailsProperties.getRedis();
        if (StringUtils.isEmpty(redis.getSentinelMaster())) {
            // 如果哨兵配置为空，则走常规redis配置
            this.jedisPool = new JedisPool(
                    new JedisPoolConfig(),
                    redis.getHost(),
                    redis.getPort(),
                    redis.getTimeout(),
                    redis.getPassword(),
                    redis.getDatabase()
            );
        } else {
            // 如果master不为空，走哨兵模式
            logger.info("sentinel master: {}, sentinel nodes: {}", redis.getSentinelMaster(), redis.getSentinelNodes());
            jedisPool = new JedisSentinelPool(
                    this.galioClientDetailsProperties.getRedis().getSentinelMaster(),
                    this.galioClientDetailsProperties.getRedis().getSentinelNodes(),
                    new GenericObjectPoolConfig(),
                    this.galioClientDetailsProperties.getRedis().getTimeout(),
                    this.galioClientDetailsProperties.getRedis().getPassword(),
                    this.galioClientDetailsProperties.getRedis().getDatabase());
        }
    }

    private String getString(String key) {
        Jedis jedis = null;
        String result = null;
        try {
            jedis = this.jedisPool.getResource();
            result = jedis.get(key);
        } catch (Exception e) {
            logger.info("jedis get resource failed!:{}", e.getMessage());
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    private boolean setString(String key, String value, int seconds) {
        Jedis jedis = null;
        try {
            jedis = this.jedisPool.getResource();
            jedis.setex(key, seconds, value);
            return true;
        } catch (Exception e) {
            logger.info("jedis set resource failed!:{}", e.getMessage());
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    private boolean delete(String key) {
        Jedis jedis = null;
        try {
            jedis = this.jedisPool.getResource();
            long i = jedis.del(key);
            if (i != 1L) {
                return false;
            }
            return true;
        } catch (Exception e) {
            logger.info("jedis set resource failed!:{}", e.getMessage());
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public String getPlatformResources(String type) {
        String urlKey = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":resourceType_" + type;
        String urlResult = getString(urlKey);
        return  urlResult;
    }

    public String getPlatformUserResource(String username) {
        String userKey = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":username_" + username;
        String userResult = getString(userKey);
        return userResult;
    }

    /**
     * 获取缓存中的token，key为rms.platform_4:token:xxxxxx
     *
     * @Param [token]
     * @return java.lang.String
     **/
    public GalioOauthAccessToken getToken(String token) {
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token:" + token;
        GalioOauthAccessToken accessToken = null;
        try {
            accessToken = JSON.parseObject(getString(key), GalioOauthAccessToken.class);
        } catch (Exception e) {
            logger.info("获取redis缓存中的token失败：{}", e.getMessage());
        }
        return accessToken;
    }

    /**
     * redis缓存token
     *
     * @Param [token, accessToken]
     * @return boolean
     **/
    public boolean saveToken(GalioOauthAccessToken accessToken) {
        Long expires = (accessToken.getExpiration().getTime() - System.currentTimeMillis()) / 1000;
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token:" + accessToken.getAccessToken();
        return setString(key, JSON.toJSONString(accessToken), expires.intValue());
    }

    public boolean removeToken(String accessToken) {
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token:" + accessToken;
        return delete(key);
    }

    /**
     * 获取缓存中的token用户对应关系，key为rms.platform_4:token.user:xxxxxx
     *
     * @Param [token]
     * @return java.lang.String
     **/
    public UserDetails getAuthTokenUserDetails(String token) {
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token.user:" + token;
        UserDetails userDetails = null;
        try {
            userDetails = JSON.parseObject(getString(key), UserDetails.class);
        } catch (Exception e) {
            logger.info("获取redis缓存中的token用户关系失败：{}", e.getMessage());
        }
        return userDetails;
    }

    public boolean saveTokenUserDetails(GalioOauthAccessToken token, UserDetails userDetails) {
        Long expires = (token.getExpiration().getTime() - System.currentTimeMillis()) / 1000;
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token.user:" + token.getAccessToken();
        return setString(key, JSON.toJSONString(userDetails), expires.intValue());
    }

    public boolean removeTokenUserDetails(String token) {
        String key = "rms.platform_" + galioClientDetailsProperties.getClientId() + ":token.user:" + token;
        return delete(key);
    }

    public GalioOauthAccessToken getAccessTokenByPlatFormAndTokenStr(String platform, String tokenStr) {
        String key = "rms.platform_" + platform + ":token:" + tokenStr;
        GalioOauthAccessToken accessToken = null;
        try {
            accessToken = JSON.parseObject(getString(key), GalioOauthAccessToken.class);
        } catch (Exception e) {
            logger.info("根据平台 {} 和 tokenStr {} 获取redis缓存中的token失败：{}",platform, tokenStr, e.getMessage());
        }
        return accessToken;
    }

    public UserDetails getUserByPlatformAndTokenStr(String platform, String tokenStr) {
        String key = "rms.platform_" + platform + ":token.user:" + tokenStr;
        UserDetails userDetails = null;
        try {
            userDetails = JSON.parseObject(getString(key), UserDetails.class);
        } catch (Exception e) {
            logger.info("根据平台 {} 和 tokenStr {} 获取redis缓存中的token用户关系失败：{}", platform, tokenStr, e.getMessage());
        }
        return userDetails;
    }
}
